
class Base {
    private int x;
    private int y;

    public Base(int x,int y) {
        this.y = y;
        this.x = x;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int add(int a, int b) {
        return a+b;
    }
    public int add(int a,int b ,int c ) {
        return a+b+c;
    }
    //编译器会根据我们的参数的个数和类型来选择调用我们的方法，这个就叫做编译时绑定（也叫静态绑定）


}
class Sub extends Base {
    private int z;

    public Sub(int x,int y,int z) {
        super(x,y);
        this.z = z;
    }
    public int getZ() {
        return z;
    }
    public int calculate() {
        return super.getX() * super.getY()*this.getZ();
    }
}
class Animal {
    public String name;
    public int age;
    public Animal() {
        eat();//name在这个地方没有被赋值
        System.out.println("不带参数的构造方法！Animal");
    }
    public Animal (String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(this.name + "正在吃饭");
    }
}

class Cat extends Animal {
    public Cat() {
        super("哈哈",5);
        System.out.println("不带参数的Cat");
    }
    public void mimi() {
        System.out.println(this.name + "正在喵喵喵");
    }

    public void eat() {
        System.out.println(this.name + "正在吃猫粮 ");
    }

}

class Dog extends Animal {
    public Dog() {
        System.out.println("不带参数的Dog");
    }
    public Dog(String name, int age) {
        super(name,age);
    }
    public void bark() {
        System.out.println(this.name+ "正在汪汪");
    }
    @Override
    //这个注解就会帮我们去检查我们是否重写正确
    //对eat方法的重写
    //只有方法内部有区别
    //重写的条件：1.返回类型必须相同（或者为父子类关系）
    //2.方法名相同
    //3.参数列表相同
    //当我们把void 改为Cat，将父类的eat方法的返回值类型改为Animal ，这就是返回值的类型属于父子类关系
    public void eat() {
        System.out.println(this.name + "正在吃狗粮");
    }
}
    public class Test {
        public static void main(String[] args) {
            Animal animal = new Dog();//但是调用的还是Dog引用的方法
        }
        public static void main5(String[] args) {
            Animal animal = new Dog("wangwang",15);
            if(animal instanceof Cat) {
                //instanceof是
                Cat cat = (Cat) animal;//因为我们本身引用Dog，但是强转为Cat，所以运行之后会报错
                cat.mimi();//运行之后他就会报错，但是没有运行的时候是没有报错的
            }
            Dog dog = (Dog)animal;
            dog.bark();
        }
    public static void testFunc(Animal animal) {
        animal.eat();
    }

    public static void main4(String[] args) {
        Dog dog = new Dog("汪汪",1);
        testFunc(dog);

        Cat cat = new Cat();
        testFunc(cat);

        }
    public static Animal testFunc2() {
        return new Dog();
    }

    public static void main3(String[] args) {
        Dog dog = new Dog("汪汪",1);
        testFunc(dog);//将子类对象给到了父类的引用
        //这个就是通过参数的传递发生了向上转型
        }
    //向上转型
    public static void main2(String[] args) {
        /*Dog dog = new Dog("汪汪",1);
        Animal animal = dog;//这个就是向上转型*/
        //下面这行代码与上面两行代码等价
        Animal animal = new Dog("wangwang",15);
        //animal.bark;//是不可以通过父类引用去调用Dog对象的方法的
        animal.eat();//但是这里调用的是Dog中的eat方法，这就叫做动态绑定（运行时绑定）
        //编译的时候确实是调用的是Animal的eat，但是运行之后的结果是子类的
        //这个过程就叫做运行时的绑定      这个就是发生了重写并且是通过父类引用来调用这个重写的方法

        }


        public static void main1(String[] args) {
            Dog dog = new Dog("汪汪",1);
            dog.eat();//我们此时的Dog类有eat方法所以就会调用自己的方法（也就是重写方法）

        }

}
